package com.tools.alivideo;

import com.aliyun.vod.upload.impl.UploadVideoImpl;
import com.aliyun.vod.upload.req.UploadURLStreamRequest;
import com.aliyun.vod.upload.req.UploadVideoRequest;
import com.aliyun.vod.upload.resp.UploadURLStreamResponse;
import com.aliyun.vod.upload.resp.UploadVideoResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.exceptions.ServerException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoRequest;
import com.aliyuncs.vod.model.v20170321.CreateUploadVideoResponse;
import org.apache.commons.lang.StringUtils;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.security.SignatureException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by luqing on 18/1/16.
 */
public class TestOpenAPI {

//    public static String access_key_id = "LTbIw6J5Mas3danq";
//    public static String access_key_secret = "ddnrBObSNs801cterEhGa8njeLqyt7";

    public static String access_key_id = "自己的accesskey";
    public static String access_key_secret = "自己的secret";

    private static DefaultAcsClient aliyunClient = new DefaultAcsClient(DefaultProfile.getProfile("cn-shanghai", access_key_id, access_key_secret));


    public static String listJobUrl(String jobs) throws Exception{
        Map<String, String> publicParams = new HashMap();
        publicParams.put("Format", "JSON");
        publicParams.put("Version", "2017-03-21");
        publicParams.put("AccessKeyId", access_key_id);
        publicParams.put("SignatureMethod", "HMAC-SHA1");
        publicParams.put("Timestamp",  generateTimestamp());
        publicParams.put("SignatureVersion", "1.0");
        publicParams.put("SignatureNonce", generateRandom());

        Map<String, String> privateParams = new HashMap();
        String domain = "http://vod.cn-shanghai.aliyuncs.com";
        privateParams.put("Action", "ListAIJob");
        privateParams.put("JobIds", jobs);
        String url = getFinalUrl(domain, "GET", publicParams, privateParams);
        System.out.print(url);
        return url;
    }


    public static String createJobUrl(String mediaId) throws Exception{
        Map<String, String> publicParams = new HashMap();
        publicParams.put("Format", "JSON");
        publicParams.put("Version", "2017-03-21");
        publicParams.put("AccessKeyId", access_key_id);
        publicParams.put("SignatureMethod", "HMAC-SHA1");
        publicParams.put("Timestamp",  generateTimestamp());
        publicParams.put("SignatureVersion", "1.0");
        publicParams.put("SignatureNonce", generateRandom());

        Map<String, String> privateParams = new HashMap();
        String domain = "http://vod.cn-shanghai.aliyuncs.com";
        privateParams.put("Action", "SubmitAIJob");
        privateParams.put("MediaId", mediaId);
        privateParams.put("Types", "AIVideoCover,AIVideoCategory,AIVideoSummary,AIVideoCensor,AIVideoAnnotation");
//        privateParams.put("Category", "Celebrity");
        String url = getFinalUrl(domain, "GET", publicParams, privateParams);
        System.out.print(url);
        return url;
    }



    public static String generateRandom() {
        String signatureNonce = UUID.randomUUID().toString();
        return signatureNonce;
    }

    public static String generateTimestamp() {
//        例如，2014-7-29T12:00:00Z(为北京时间2014年7月29日的20点0分0秒
        Date data = new Date(System.currentTimeMillis() - 28800000);
        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
        return dateFormat.format(data);
    }

    /**
     * @param domain        请求地址
     * @param method        请求方式 ，GET，POST等
     * @param publicParams  公共参数
     * @param privateParams 接口的私有参数
     * @return 最后的url
     */
    public static String getFinalUrl(String domain, String method, Map<String, String> publicParams, Map<String, String> privateParams) {
        List<String> allEncodeParams = getAllParams(publicParams, privateParams);
        String cqsString = getCQS(allEncodeParams);
        String stringtoSign = getStringtoSign(method, cqsString);
        String signStr = getSign(access_key_secret, stringtoSign);
        String finalUrl = domain + "?" + cqsString + "&" + getUrlEncode("Signature") + "=" + getUrlEncode(signStr);

        return finalUrl;
    }

    private static String getSign(String accessSecret, String stringtoSign) {
        try {
            String key = accessSecret + "&";
            String signature = calculateRFC2104HMAC(stringtoSign, key);
            return signature;

        } catch (SignatureException e) {
            e.printStackTrace();
        }
        return "";
    }

    private static String getStringtoSign(String method, String cqsString) {
        String stringToSign = method + "&" + getUrlEncode("/") + "&" + getUrlEncode(cqsString);

        return stringToSign;
    }

    private static List<String> getAllParams(Map<String, String> publicParams, Map<String, String> privateParams) {
        List<String> encodeParams = new ArrayList<String>();

        if (publicParams != null) {
            for (String key : publicParams.keySet()) {

                String value = publicParams.get(key);
                //将参数和值都urlEncode一下。
                String encodeKey = getUrlEncode(key);
                String encodeVal = getUrlEncode(value);

                encodeParams.add(encodeKey + "=" + encodeVal);
            }
        }
        if (privateParams != null) {
            for (String key : privateParams.keySet()) {
                String value = privateParams.get(key);
                //将参数和值都urlEncode一下。
                String encodeKey = getUrlEncode(key);
                String encodeVal = getUrlEncode(value);

                encodeParams.add(encodeKey + "=" + encodeVal);
            }
        }

        return encodeParams;
    }

    /**
     * 参数urlEncode
     * @param value
     * @return
     */
    public static String getUrlEncode(String value) {
        try {
            String urlEncodeOrignStr = URLEncoder.encode(value, "UTF-8");
            String plusReplaced = urlEncodeOrignStr.replace("+", "%20");
            String starReplaced = plusReplaced.replace("*", "%2A");
            String waveReplaced = starReplaced.replace("%7E", "~");
            return waveReplaced;
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return value;
    }

    /**
     * 获取CQS 的字符串
     *
     * @param allParams
     * @return
     */
    private static String getCQS(List<String> allParams) {

        ParamsComparator paramsComparator = new ParamsComparator();
        Collections.sort(allParams, paramsComparator);

        String cqString = "";
        for (int i = 0; i < allParams.size(); i++) {
            cqString += allParams.get(i);
            if (i != allParams.size() - 1) {
                cqString += "&";
            }
        }

        return cqString;
    }


    private static class ParamsComparator implements Comparator<String> {

        public int compare(String lhs, String rhs) {
            return lhs.compareTo(rhs);
        }
    }

    private static final String HMAC_SHA1_ALGORITHM = "HmacSHA1";
    /**
     * Computes RFC 2104-compliant HMAC signature.
     * * @param data
     * The data to be signed.
     * @param key
     * The signing key.
     * @return
     * The Base64-encoded RFC 2104-compliant HMAC signature.
     * @throws
     * SignatureException when signature generation fails
     */
    public static String calculateRFC2104HMAC(String data, String key)
            throws SignatureException
    {
        String result;
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
            Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(data.getBytes());
            result = encode(rawHmac);
        } catch (Exception e) {
            throw new SignatureException("Failed to generate HMAC : " + e.getMessage());
        }
        return result;
    }

    public static String encode(final byte[] bytes) {
        return Base64.getEncoder().encodeToString(bytes);
    }




    public static String testUploadURLStream(String accessKeyId, String accessKeySecret, String title, String fileName, String url) {
        UploadURLStreamRequest request = new UploadURLStreamRequest(accessKeyId, accessKeySecret, title, fileName, url);
        request.setShowWaterMark(true);             //是否使用默认水印
        //request.setCallback("http://test.3boxs.com/aliyun/createJob.do");//设置上传完成后的回调URL(可选)

        UploadVideoImpl uploader = new UploadVideoImpl();
        UploadURLStreamResponse response = uploader.uploadURLStream(request);

        if(response!=null){
            return response.getVideoId();
        }

        return StringUtils.EMPTY;
    }

    public static void main(String[] args) throws Exception {
        TestOpenAPI.createJobUrl("945fba562e9d44dc9c1bd7907a894f22");
//        TestOpenAPI.listJobUrl("efef75f95bc64936bad111bcfe1038ff,8cebdccbf1b344f3bd09ed8abbaea96e");
//
//
//
//        TestOpenAPI.testUploadURLStream(access_key_id,access_key_secret,"test","test.mp4",
//                "http://jianshan.oss-cn-hangzhou.aliyuncs.com/%E9%92%89%E9%92%89.mp4?Expires=1519901792&OSSAccessKeyId=LTAIzt0dq511oMi6&Signature=JG76xi1DKT%2BwAg4UexDtGqPUFFc%3D");
    }


}
